package com.tencent.qf.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mysql.cj.util.StringUtils;
import com.tencent.qf.common.config.properties.WxMIniProgramProperties;
import com.tencent.qf.common.enums.AwardTypeEnum;
import com.tencent.qf.common.enums.UserLevelEnum;
import com.tencent.qf.common.exception.ErrorCode;
import com.tencent.qf.common.gateway.activitymanager.ActivityManagerService;
import com.tencent.qf.common.gateway.activitymanager.DTO.SignRulerSettingsInfoDTO;
import com.tencent.qf.common.gateway.mks.MKSGatewayService;
import com.tencent.qf.common.gateway.mks.dto.MksCouponStatusCountDTO;
import com.tencent.qf.common.gateway.mks.dto.MksCouponStatusCountReq;
import com.tencent.qf.common.gateway.mks.dto.MksJdCouponStatusCountBatchReq;
import com.tencent.qf.common.gateway.mks.dto.MksJdCouponStatusCountDTO;
import com.tencent.qf.common.pojo.HttpResult;
import com.tencent.qf.common.redis.RedisKeyConstants;
import com.tencent.qf.common.redis.RedisService;
import com.tencent.qf.common.util.RateLimiterUtil;
import com.tencent.qf.common.util.SpringContextUtils;
import com.tencent.qf.common.zhiyan.ZhiyanLogUtil;
import com.tencent.qf.user.config.properties.UserInfoProperties;
import com.tencent.qf.user.config.properties.UserPaymentInfoProperties;
import com.tencent.qf.user.convert.UserConvert;
import com.tencent.qf.user.dal.OrderDO;
import com.tencent.qf.user.dal.TyOrder;
import com.tencent.qf.user.dal.UserCoreInfo;
import com.tencent.qf.user.dal.UserDO;
import com.tencent.qf.user.dal.UserExample;
import com.tencent.qf.user.dal.UserRelationRecord;
import com.tencent.qf.user.dal.UserTutorRelation;
import com.tencent.qf.user.dal.entity.DepartmentDO;
import com.tencent.qf.user.dal.entity.DwmUserModelInfoRt;
import com.tencent.qf.user.dal.entity.IrisUserChangeLog;
import com.tencent.qf.user.dal.mapper.IrisUserChangeLogMapper;
import com.tencent.qf.user.dal.mapper.UserInfoMapper;
import com.tencent.qf.user.dal.mapper.UserTagMapper;
import com.tencent.qf.user.dao.TyOrderDao2;
import com.tencent.qf.user.dao.UserChannelAccountMapper;
import com.tencent.qf.user.dao.UserCoreInfoMapper;
import com.tencent.qf.user.dao.UserDao;
import com.tencent.qf.user.dao.UserRelationRecordMapper;
import com.tencent.qf.user.dao.UserTutorRelationMapper;
import com.tencent.qf.user.dto.UnionIdPaymentCount;
import com.tencent.qf.user.dto.UserBasicInfo;
import com.tencent.qf.user.dto.UserInfoDetail;
import com.tencent.qf.user.dto.UserOpenIdInfo;
import com.tencent.qf.user.dto.request.BatchOrderInfoRequest;
import com.tencent.qf.user.dto.request.EfficientOrderNumRequest;
import com.tencent.qf.user.dto.request.OrderInfoByPlainOrderIdRequest;
import com.tencent.qf.user.dto.request.OrderInfoByUidRequest;
import com.tencent.qf.user.dto.request.ParentInfoBatchRequest;
import com.tencent.qf.user.dto.request.QueryAOrderNumAllRequest;
import com.tencent.qf.user.dto.request.QueryAOrderNumBySkuIdRequest;
import com.tencent.qf.user.dto.request.QueryLotteryAwardInfoRequest;
import com.tencent.qf.user.dto.request.TeamUserInfoRequest;
import com.tencent.qf.user.dto.request.UpgradeTimeRequest;
import com.tencent.qf.user.dto.request.UserBasicInfoBatchRequest;
import com.tencent.qf.user.dto.request.UserInfoByUidUnionIdRequest;
import com.tencent.qf.user.dto.request.UserInfoDTO;
import com.tencent.qf.user.dto.request.UserInfoForGoldDetailRequest;
import com.tencent.qf.user.dto.request.UserPaymentInfoIncludeJdGiftCouponReq;
import com.tencent.qf.user.dto.request.UserRelationRecordBatchRequest;
import com.tencent.qf.user.dto.request.UserRelationTutorBatchRequest;
import com.tencent.qf.user.dto.response.AOrderNumInfo;
import com.tencent.qf.user.dto.response.EfficientOrderNumInfo;
import com.tencent.qf.user.dto.response.IrisUserInfoDTO;
import com.tencent.qf.user.dto.response.IsEditNickNameOrHeadUrlResponse;
import com.tencent.qf.user.dto.response.LotteryAwardInfo;
import com.tencent.qf.user.dto.response.OrderInfo;
import com.tencent.qf.user.dto.response.OrderInfoByUid;
import com.tencent.qf.user.dto.response.ParentInfo;
import com.tencent.qf.user.dto.response.UpgradeTimeInfo;
import com.tencent.qf.user.dto.response.UserInfoForGoldDetail;
import com.tencent.qf.user.dto.response.UserPaymentCountCacheDTO;
import com.tencent.qf.user.dto.response.UserPaymentCountDTO;
import com.tencent.qf.user.dto.response.UserTagInfo;
import com.tencent.qf.user.service.DwmUserModelInfoRtService;
import com.tencent.qf.user.service.UserCoreInfoService;
import com.tencent.qf.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.tencent.qf.common.exception.ErrorCode.INTERNAL_SERVER_ERROR;
import static org.springframework.util.CollectionUtils.isEmpty;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao;
    @Resource
    private TyOrderDao2 tyOrderDao2;
    @Resource
    private RedisService redisService;

    @Resource
    private UserInfoProperties userInfoProperties;

    @Resource
    private DwmUserModelInfoRtService dwmUserModelInfoRtService;

    @Resource
    private UserPaymentInfoProperties userPaymentInfoProperties;

    @Autowired
    private MKSGatewayService mksGatewayService;
    @Autowired
    private UserRelationRecordMapper userRelationRecordMapper;
    @Autowired
    private UserChannelAccountMapper userChannelAccountMapper;
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private ActivityManagerService activityManagerService;

    @Resource
    private UserCoreInfoMapper userCoreInfoMapper;

    @Resource
    private UserTutorRelationMapper userTutorRelationMapper;

    @Autowired
    private WxMIniProgramProperties wxMIniProgramProperties;

    @Resource
    private RateLimiterUtil rateLimiterUtil;

    @Resource
    private UserCoreInfoService userCoreInfoService;

    @Resource
    private UserTagMapper userTagMapper;

    @Resource
    private IrisUserChangeLogMapper irisUserChangeLogMapper;


    /**
     * 用户分层-用户下单情况
     *
     * @param userInfoDTO
     * @return
     */
    @Override
    public HttpResult<UserPaymentCountDTO> userPaymentInfo(UserInfoDTO userInfoDTO) {
        if (userPaymentInfoProperties.getVersion() == 1) {
            String unionId = userInfoDTO.getUnionId();
            UserPaymentCountDTO userPaymentCountDTO = new UserPaymentCountDTO();
            userPaymentCountDTO.setUnionId(unionId);
            MksCouponStatusCountReq req = new MksCouponStatusCountReq();
            req.setStatus(new String[]{"USED"});
            req.setWechat_user_union_id(unionId);
//        req.setCreate_time_end(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            List<MksCouponStatusCountDTO> dtos = mksGatewayService.mksCouponStatusCount(req);
//        List<OrderDO> list = tyOrderDao2.selectPayByUnionId(unionId);
            Integer orderCount = tyOrderDao2.selectPayByUnionIdCount(unionId);

            this.setValueByPaymentCount(userPaymentCountDTO, orderCount, dtos);
            userPaymentCountDTO.setOrderCount(orderCount);
            userPaymentCountDTO.setCouponUsedCount(isEmpty(dtos) ? 0 : dtos.get(0).getCount());
            return HttpResult.success(userPaymentCountDTO);
        } else {
            return HttpResult.success(userPaymentInfoV2(userInfoDTO));
        }
    }

    @Override
    public UserPaymentCountDTO userPaymentInfoV2(UserInfoDTO userInfoDTO) {
        String unionId = userInfoDTO.getUnionId();
        DwmUserModelInfoRt userPaymentInfoByDWN = dwmUserModelInfoRtService.getUserPaymentInfoByDWN(unionId);
        UserPaymentCountDTO userPaymentCountDTO = new UserPaymentCountDTO();
        userPaymentCountDTO.setUnionId(unionId);
        // 没有数据 为新用户
        if (userPaymentInfoByDWN == null) {
            userPaymentCountDTO.setUserType("1");
        } else {
            this.setValueByPaymentCountV2(userPaymentCountDTO, userPaymentInfoByDWN.getAccDealOrdNum(), userPaymentInfoByDWN.getCouponUsedNumNoGhost());
            userPaymentCountDTO.setOrderCount(Math.toIntExact(userPaymentInfoByDWN.getAccDealOrdNum()));
            userPaymentCountDTO.setCouponUsedCount(Math.toIntExact(userPaymentInfoByDWN.getCouponUsedNumNoGhost()));
        }
        return userPaymentCountDTO;
    }

    @Override
    public UserPaymentCountDTO userPaymentInfoIncludeJdGiftCoupon(UserPaymentInfoIncludeJdGiftCouponReq request) {
        String unionId = request.getUnionId();
        String uid = request.getUid();
        // 获取订单数量和微信代金券数量
        DwmUserModelInfoRt userPaymentInfoByDWN = dwmUserModelInfoRtService.getUserPaymentInfoByDWN(unionId);
        UserPaymentCountDTO userPaymentCountDTO = new UserPaymentCountDTO();
        userPaymentCountDTO.setUnionId(unionId);
        userPaymentCountDTO.setUid(request.getUid());
        // 获取京享礼金数量
        MksJdCouponStatusCountBatchReq req = new MksJdCouponStatusCountBatchReq();
        req.setStatus(new String[]{"USED"});
        req.setUids(new String[]{uid});
        Map<String, List<MksJdCouponStatusCountDTO>> uidJdCouponInfos = mksGatewayService.mksJdCouponStatusCountBatch(req);
        List<MksJdCouponStatusCountDTO> dtos = uidJdCouponInfos.get(uid);

        Long couponCount = (long) (CollectionUtils.isEmpty(dtos) ? 0 : dtos.get(0).getCount());
        Long orderCount = 0L;

        if(request.getIncludeCreatedStatus()) {
            orderCount = tyOrderDao2.selectPayByUnionIdCountWithCreate(unionId);
            log.info("用户:{}, 待支付订单数：{}", unionId, orderCount);
        }

        userPaymentCountDTO.setJdCouponUsedCount(Math.toIntExact(couponCount));

        if(userPaymentInfoByDWN != null){
            orderCount += userPaymentInfoByDWN.getAccDealOrdNum();
            couponCount += userPaymentInfoByDWN.getCouponUsedNumNoGhost();
        }

        this.setValueByPaymentCountV2(userPaymentCountDTO, orderCount , couponCount);
        userPaymentCountDTO.setOrderCount(Math.toIntExact(orderCount));
        userPaymentCountDTO.setCouponUsedCount(Math.toIntExact(couponCount));
        return userPaymentCountDTO;
    }

    @Override
    public HttpResult<List<UserPaymentCountDTO>> batchUserPaymentInfo(List<UserInfoDTO> userInfoDTOs) {
        if (!isEmpty(userInfoDTOs) && userInfoDTOs.size() > 50) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过50");
        }
        // 封装所有用户分层信息
        List<UserPaymentCountDTO> resp = new ArrayList<>();
        // 批量获取所有用户的订单
        List<UnionIdPaymentCount> unionIdPaymentCounts = tyOrderDao2.selectPayByUnionIdsCount(userInfoDTOs);
        Map<String, UnionIdPaymentCount> userOrderMap = unionIdPaymentCounts.stream().collect(Collectors.toMap(UnionIdPaymentCount::getUnionId, e -> e));
        HashMap<String, List<MksCouponStatusCountDTO>> countMap = getCouponCountMap(userInfoDTOs);
        if (countMap == null) {
            return HttpResult.error(INTERNAL_SERVER_ERROR);
        }
        for (UserInfoDTO userInfoDTO : userInfoDTOs) {
            UserPaymentCountDTO userPaymentCountDTO = new UserPaymentCountDTO();
            userPaymentCountDTO.setUnionId(userInfoDTO.getUnionId());
            Integer count = userOrderMap.getOrDefault(userInfoDTO.getUnionId(), new UnionIdPaymentCount()).getDealOrdNum();
            List<MksCouponStatusCountDTO> mksCouponStatusCountDTOS = countMap.get(userInfoDTO.getUnionId());
            this.setValueByPaymentCount(userPaymentCountDTO, count, mksCouponStatusCountDTOS);
            userPaymentCountDTO.setOrderCount(count);
            userPaymentCountDTO.setCouponUsedCount(isEmpty(mksCouponStatusCountDTOS) ? 0 : mksCouponStatusCountDTOS.get(0).getCount());
            resp.add(userPaymentCountDTO);
        }
        return HttpResult.success(resp);
    }

    @Override
    public HttpResult<List<UserPaymentCountDTO>> batchUserPaymentInfoV2(List<UserInfoDTO> userInfoDTOs) {
        if (!isEmpty(userInfoDTOs) && userInfoDTOs.size() > 50) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过50");
        }
        List<String> unionIds = userInfoDTOs.stream().map(UserInfoDTO::getUnionId).collect(Collectors.toList());
        // 封装所有用户分层信息
        List<UserPaymentCountDTO> resp = new ArrayList<>(userInfoDTOs.size());

        List<DwmUserModelInfoRt> userPaymentInfoByDWNs = dwmUserModelInfoRtService.getUserPaymentInfoByDWNs(unionIds);

        Map<String, DwmUserModelInfoRt> userPaymentInfoMap = userPaymentInfoByDWNs.stream().collect(Collectors.toMap(DwmUserModelInfoRt::getUnionId, a -> a, (k1, k2) -> k1));

        for (UserInfoDTO userInfoDTO : userInfoDTOs) {
            UserPaymentCountDTO userPaymentCountDTO = new UserPaymentCountDTO();
            userPaymentCountDTO.setUnionId(userInfoDTO.getUnionId());
            if (!userPaymentInfoMap.containsKey(userInfoDTO.getUnionId())) {
                userPaymentCountDTO.setUserType("1");
            } else {
                DwmUserModelInfoRt dwmUserModelInfoRt = userPaymentInfoMap.get(userInfoDTO.getUnionId());
                this.setValueByPaymentCountV2(userPaymentCountDTO, dwmUserModelInfoRt.getAccDealOrdNum(), dwmUserModelInfoRt.getCouponUsedNumNoGhost());
                userPaymentCountDTO.setOrderCount(Math.toIntExact(dwmUserModelInfoRt.getAccDealOrdNum()));
                userPaymentCountDTO.setCouponUsedCount(Math.toIntExact(dwmUserModelInfoRt.getCouponUsedNumNoGhost()));
            }
            resp.add(userPaymentCountDTO);
        }
        return HttpResult.success(resp);
    }

    /**
     * 团长uid查询接口
     *
     * @param request
     */
    @Override
    public HttpResult<List<IrisUserInfoDTO>> teamUserInfo(TeamUserInfoRequest request) {
        List<IrisUserInfoDTO> irisUserInfoDTOS = userInfoMapper.teamUserInfo(request);
        return HttpResult.success(irisUserInfoDTOS);
    }

    @Override
    public HttpResult<LotteryAwardInfo> getAwardPoolInfo(QueryLotteryAwardInfoRequest request) {
        LotteryAwardInfo lotteryAwardInfo = new LotteryAwardInfo();
        // 1、 获取用户分层
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setUnionId(request.getUnionId());
        HttpResult<UserPaymentCountDTO> userPaymentCountDTOHttpResult = userPaymentInfo(userInfoDTO);
        String userPaymentInfo = userPaymentCountDTOHttpResult.getData().getUserType();
        // 2、 获取用户openid、type、level
        UserOpenIdInfo openIdInfo = userInfoMapper.getOpenIdInfo(request.getUnionId());
        // 用户非空判断
        if (openIdInfo == null) {
            return HttpResult.error(ErrorCode.USER_NOT_EXIST);
        }
        // 3、 根据用户分层、等级、账户类型获取奖池id
        String awardPoolId = "";
        List<SignRulerSettingsInfoDTO> signRuleConfigList = activityManagerService.getSignRuleConfigList();
        for (SignRulerSettingsInfoDTO signRulerSettingsInfoDTO : signRuleConfigList) {
            // 匹配的规则
            if (signRulerSettingsInfoDTO.getUserType().contains(userPaymentInfo)
                    && signRulerSettingsInfoDTO.getAccountType().contains(openIdInfo.getType())
                    && signRulerSettingsInfoDTO.getUserLevel().contains(openIdInfo.getLevelId())) {
                // 奖池为金币 返回空
                if (String.valueOf(signRulerSettingsInfoDTO.getAwardType()).equals(AwardTypeEnum.WECHAT_COUPON.getType())) {
                    awardPoolId = signRulerSettingsInfoDTO.getAwardPoolId();
                } else {
                    return HttpResult.error(ErrorCode.AWARD_POOL_TYPE_IS_GOLD);
                }
                break;
            }
        }
        if (Strings.isEmpty(awardPoolId)) {
            return HttpResult.error(ErrorCode.AWARD_POOL_ID_IS_NULL);
        }
        // 4、 设置属性
        lotteryAwardInfo.setUserPaymentInfo(Integer.valueOf(userPaymentInfo));
        lotteryAwardInfo.setAwardPoolId(awardPoolId);
        lotteryAwardInfo.setOpenId(openIdInfo.getWxOpenId());
        lotteryAwardInfo.setAppId(wxMIniProgramProperties.getAppId());
        return HttpResult.success(lotteryAwardInfo);
    }

    @Override
    public HttpResult<List<String>> compareUserPaymentInfo(Integer minPage, Integer maxPage, Integer size) {
        minPage = minPage == null ? 1 : minPage;
        maxPage = maxPage == null ? 1 : maxPage;
        size = size == null ? 50 : size;
        Integer page = minPage;
        ArrayList<String> failUsers = new ArrayList<>();
        while (page <= maxPage) {
            IPage<DwmUserModelInfoRt> userPaymentInfoPage = dwmUserModelInfoRtService.getUserPaymentInfoPage(page, size);
            HashMap<String, CompletableFuture<Boolean>> map = new HashMap<>();
            for (DwmUserModelInfoRt dwmUserModelInfoRt : userPaymentInfoPage.getRecords()) {
                UserService userService = SpringContextUtils.getBean(UserService.class);
                CompletableFuture<Boolean> compare = userService.compare(dwmUserModelInfoRt);
                map.put(dwmUserModelInfoRt.getUnionId(), compare);
            }
            Set<String> unionIds = map.keySet();
            for (String unionId : unionIds) {
                CompletableFuture<Boolean> compare = map.get(unionId);
                try {
                    if (!compare.get()) {
                        failUsers.add(unionId);
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (ExecutionException e) {
                    throw new RuntimeException(e);
                }
            }
            page++;
        }
        return HttpResult.success(failUsers);
    }

    @Override
    @Async("asyncMarketServiceExecutor")
    public CompletableFuture<Boolean> compare(DwmUserModelInfoRt dwmUserModelInfoRt) {
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setUnionId(dwmUserModelInfoRt.getUnionId());
        rateLimiterUtil.acquire(1);
        String userType = userPaymentInfo(userInfoDTO).getData().getUserType();
        String userType1 = userPaymentInfoV2(userInfoDTO).getUserType();
        if (!Objects.equals(userType, userType1)) {
            log.error("用户分层数据不匹配， unionId:" + dwmUserModelInfoRt.getUnionId());
            return CompletableFuture.completedFuture(false);
        }
        log.info("用户分层数据匹配， unionId:" + dwmUserModelInfoRt.getUnionId());
        return CompletableFuture.completedFuture(true);
    }

    @Override
    public HttpResult<List<OrderInfo>> getOrderInfos(BatchOrderInfoRequest request) {
        if (!isEmpty(request.getOrderIds()) && request.getOrderIds().size() > 50) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过50");
        }
        List<TyOrder> orders = tyOrderDao2.getOrderInfos(request.getUid(), request.getOrderIds());
        List<OrderInfo> orderInfos = new ArrayList<>();
        for (TyOrder order : orders) {
            OrderInfo orderInfo = UserConvert.INSTANCE.tyOrder2OrderInfo(order);
            orderInfos.add(orderInfo);
        }
        return HttpResult.success(orderInfos);
    }

    @Override
    public HttpResult<List<UserTutorRelation>> userRelationTutorBatch(UserRelationTutorBatchRequest request) {
        if (!isEmpty(request.getUids()) && request.getUids().size() > 50) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过50");
        }
        List<UserTutorRelation> list = userTutorRelationMapper.userRelationTutorBatch(request);
        return HttpResult.success(list);
    }

    @Override
    public HttpResult<UserInfoForGoldDetail> userInfoForGoldDetail(UserInfoForGoldDetailRequest request) {
        UserInfoForGoldDetail userInfoForGoldDetail = new UserInfoForGoldDetail();
        // 设置导师id
        UserRelationTutorBatchRequest userRelationTutorBatchRequest = new UserRelationTutorBatchRequest();
        userRelationTutorBatchRequest.setUid(request.getIrisUid());
        List<UserTutorRelation> userTutorRelations = this.userRelationTutorBatch(userRelationTutorBatchRequest).getData();
        if (userTutorRelations != null && userTutorRelations.size() > 0) {
            userInfoForGoldDetail.setTutorUid(userTutorRelations.get(0).getTutorUid());
        }
        // 设置上级uid
        UserRelationRecordBatchRequest userRelationRecordBatchRequest = new UserRelationRecordBatchRequest();
        ArrayList<String> uids = new ArrayList<>();
        uids.add(request.getIrisUid());
        userRelationRecordBatchRequest.setUids(uids);
        List<UserRelationRecord> userRelationRecords = this.userRelationRecordBatch(userRelationRecordBatchRequest).getData();
        if (userRelationRecords != null && userRelationRecords.size() > 0) {
            userInfoForGoldDetail.setParentUid(userRelationRecords.get(0).getParentUid());
        }
        // 设置区域id
        DepartmentDO areaInfoByUid = userCoreInfoService.getAreaInfoByUid(request.getIrisUid());
        if (areaInfoByUid != null) {
            userInfoForGoldDetail.setAreaId(areaInfoByUid.getDeptId());
            userInfoForGoldDetail.setAreaName(areaInfoByUid.getDeptName());
        }
        return HttpResult.success(userInfoForGoldDetail);
    }

    @Override
    public HttpResult<List<OrderInfoByUid>> getOrderInfosByUid(OrderInfoByUidRequest request) {
        UserInfoByUidUnionIdRequest userInfoByUidUnionIdRequest = new UserInfoByUidUnionIdRequest();
        userInfoByUidUnionIdRequest.setUid(request.getIrisUid());
        userInfoByUidUnionIdRequest.setSaasId(userInfoProperties.getRootSaasId());
        UserInfoDetail userInfoDetail = this.userInfoByUidUnionId(userInfoByUidUnionIdRequest).getData();
        String unionId = userInfoDetail == null ? null : userInfoDetail.getUnionId();

        List<TyOrder> orderInfosByUid = tyOrderDao2.getOrderInfosByUid(unionId, request.getIrisUid(), request.getOrderNum(), request.getIsAll());
        List<OrderInfoByUid> orderInfoByUids = UserConvert.INSTANCE.tyOrders2OrderInfosByUid(orderInfosByUid);
        return HttpResult.success(orderInfoByUids);
    }

    /**
     * 批量获取用户上级信息
     *
     * @return 用户上级信息
     */
    @Override
    public HttpResult<List<ParentInfo>> userParentInfoBatch(ParentInfoBatchRequest request) {
        if (!isEmpty(request.getUids()) && request.getUids().size() > 50) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过50");
        }
        List<ParentInfo> list = userRelationRecordMapper.userParentInfoBatch(request);
        return HttpResult.success(list);
    }

    @Override
    public HttpResult<List<EfficientOrderNumInfo>> queryEfficientOrderNum(EfficientOrderNumRequest request) {
        if (!isEmpty(request.getIrisUids()) && request.getIrisUids().size() > 200) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过200");
        }
        List<TyOrder> tyOrders = tyOrderDao2.queryEfficientOrderNumInfo(request.getIrisUids(), request.getStartDate().getTime(), request.getEndDate().getTime());
        // 根据uid分组
        Map<String, List<TyOrder>> uidOrderMap = tyOrders.stream().collect(Collectors.groupingBy(TyOrder::getMBuyerinfoCpsuid));
        ArrayList<EfficientOrderNumInfo> efficientOrderNumInfos = new ArrayList<>();
        for (String uid : uidOrderMap.keySet()) {
            EfficientOrderNumInfo efficientOrderNumInfo = new EfficientOrderNumInfo();
            // 获取uid下的所有订单， 根据订单号分组
            List<TyOrder> uidTyOrders = uidOrderMap.get(uid);
            Map<String, List<TyOrder>> orderIdMap = uidTyOrders.stream().collect(Collectors.groupingBy(TyOrder::getExternalOrderId));
            ArrayList<EfficientOrderNumInfo.EfficientOrderInfo> EfficientOrderInfos = new ArrayList<>();

            orderIdMap.keySet().forEach((orderId) -> {
                EfficientOrderNumInfo.EfficientOrderInfo efficientOrderInfo = new EfficientOrderNumInfo.EfficientOrderInfo();
                efficientOrderInfo.setOrderId(orderId);
                efficientOrderInfo.setCreateTime(orderIdMap.get(orderId).get(0).getCreateTime());
                EfficientOrderInfos.add(efficientOrderInfo);
            });

            efficientOrderNumInfo.setIrisUid(uid);
            efficientOrderNumInfo.setEfficientOrderNum(orderIdMap.keySet().size());
            efficientOrderNumInfo.setEfficientOrderInfos(EfficientOrderInfos);
            efficientOrderNumInfos.add(efficientOrderNumInfo);
        }
        return HttpResult.success(efficientOrderNumInfos);
    }

    /**
     * 查询用户有效分销单数
     *
     * @param request
     * @return
     */
    @Override
    public HttpResult<List<EfficientOrderNumInfo>> queryEfficientSplitOrder(EfficientOrderNumRequest request) {
        if (!isEmpty(request.getIrisUids()) && request.getIrisUids().size() > 200) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过200");
        }
        List<EfficientOrderNumInfo> efficientOrderNumInfos = tyOrderDao2.queryEfficientSplitOrder(request.getIrisUids(), request.getStartDate().getTime(), request.getEndDate().getTime());
        return HttpResult.success(efficientOrderNumInfos);
    }

    @Override
    public HttpResult<UpgradeTimeInfo> upgradeTime(UpgradeTimeRequest request) {
        QueryWrapper<IrisUserChangeLog> query = new QueryWrapper<>();
        query.eq("uid", request.getIrisUid())
                .eq("info", request.getLevelId())
                .orderByDesc("update_time");
        List<IrisUserChangeLog> irisUserChangeLogs = irisUserChangeLogMapper.selectList(query);
        UpgradeTimeInfo upgradeTimeInfo = new UpgradeTimeInfo();
        upgradeTimeInfo.setUpgradeTime(irisUserChangeLogs.size() > 0 ? irisUserChangeLogs.get(0).getCreateTime() : null);
        return HttpResult.success(upgradeTimeInfo);
    }

    /**
     * 查询全场A单数量批量接口
     *
     * @param request
     * @return
     */
    @Override
    public HttpResult<List<AOrderNumInfo>> queryAOrderNumAllBatch(QueryAOrderNumAllRequest request) {
        List<AOrderNumInfo> list = tyOrderDao2.queryAOrderNumAllBatch(request.getIrisUids(), request.getStartTime(),
                request.getEndTime(), request.getPaymentAmount());
        return HttpResult.success(list);
    }

    /**
     * 根据分销单号批量获取订单
     *
     * @param request
     * @return
     */
    @Override
    public HttpResult<List<OrderInfo>> orderInfosByPlainOrderId(OrderInfoByPlainOrderIdRequest request) {
        if (isEmpty(request.getPlainOrderIds())) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "请求plainOrderId数组不能为空");
        }
        if (request.getPlainOrderIds().size() > 100) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求plainOrderId数组大小不能超过100");
        }
        List<TyOrder> orders = tyOrderDao2.orderInfosByPlainOrderId(request);
        List<OrderInfo> orderInfos = new ArrayList<>();
        for (TyOrder order : orders) {
            OrderInfo orderInfo = UserConvert.INSTANCE.tyOrder2OrderInfo(order);
            orderInfos.add(orderInfo);
        }
        return HttpResult.success(orderInfos);
    }

    @Override
    public HttpResult<AOrderNumInfo> queryAOrderNumBySkuId(QueryAOrderNumBySkuIdRequest request) {
        Integer orderCount = tyOrderDao2.selectAOrderCountBySkuId(request.getSkuId(), request.getIrisUid(),
                request.getStartTime(), request.getEndTime(), request.getPaymentAmount());
        AOrderNumInfo aOrderNumInfo = new AOrderNumInfo();
        aOrderNumInfo.setOrderCount(orderCount);
        return HttpResult.success(aOrderNumInfo);
    }

    @Override
    public HttpResult<AOrderNumInfo> queryAOrderNumAll(QueryAOrderNumAllRequest request) {
        Integer orderCount = tyOrderDao2.selectAOrderNumAll(request.getSkuIds(), request.getIrisUid(),
                request.getStartTime(), request.getEndTime(), request.getPaymentAmount());
        AOrderNumInfo aOrderNumInfo = new AOrderNumInfo();
        aOrderNumInfo.setOrderCount(orderCount);
        return HttpResult.success(aOrderNumInfo);
    }

    private HashMap<String, List<MksCouponStatusCountDTO>> getCouponCountMap(List<UserInfoDTO> userInfoDTOs) {
        List<String> unionIds = userInfoDTOs.stream().map(UserInfoDTO::getUnionId).collect(Collectors.toList());
        HashMap<String, List<MksCouponStatusCountDTO>> countMap = new HashMap<>();
        HashMap<List<String>, CompletableFuture<HashMap<String, List<MksCouponStatusCountDTO>>>> completableFutureMap = new HashMap<>();
        for (List<String> unionIdPartition : ListUtils.partition(unionIds, 5)) {
            CompletableFuture<HashMap<String, List<MksCouponStatusCountDTO>>> couponCountBatch = mksGatewayService.getCouponCountBatch(unionIdPartition);
            completableFutureMap.put(unionIdPartition, couponCountBatch);
        }
        Iterator<List<String>> iterator = completableFutureMap.keySet().iterator();
        while (iterator.hasNext()) {
            List<String> unionIdPartition = iterator.next();
            int tries = 1;
            while (true) {
                try {
                    CompletableFuture<HashMap<String, List<MksCouponStatusCountDTO>>> hashMapCompletableFuture = completableFutureMap.get(unionIdPartition);
                    HashMap<String, List<MksCouponStatusCountDTO>> stringListHashMap = hashMapCompletableFuture.get();
                    countMap.putAll(stringListHashMap);
                    break;
                } catch (Exception e) {
                    if (tries <= 3) {
                        CompletableFuture<HashMap<String, List<MksCouponStatusCountDTO>>> couponCountBatch = mksGatewayService.getCouponCountBatch(unionIdPartition);
                        completableFutureMap.put(unionIdPartition, couponCountBatch);
                        tries++;
                    } else {
                        log.error("批量获取优惠券核销数，重试超过三次，unionId: " + unionIdPartition + ",error: ", e);
                        ZhiyanLogUtil.sendLog(MDC.get("trace_id"), "批量获取优惠券核销数，重试超过三次，unionId: " + unionIdPartition + ",error: " + e);
                        break;
                    }
                }
            }
        }
        return countMap;
    }

    /**
     * 批量查询用户绑定关系
     *
     * @param request
     * @return
     */
    @Override
    public HttpResult<List<UserRelationRecord>> userRelationRecordBatch(UserRelationRecordBatchRequest request) {
        if (!isEmpty(request.getUids()) && request.getUids().size() > 50) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过50");
        }
        List<UserRelationRecord> list = userRelationRecordMapper.userRelationRecordBatch(request);
        return HttpResult.success(list);
    }

    /**
     * 通过uid、unionId查询用户信息
     *
     * @param request
     * @return
     */
    @Override
    public HttpResult<UserInfoDetail> userInfoByUidUnionId(UserInfoByUidUnionIdRequest request) {
        UserInfoDetail userInfoDetail = userChannelAccountMapper.userInfoByUnionId(request);
        return HttpResult.success(userInfoDetail);
    }

    @Override
    public List<UserTagInfo> userTags(String uid, String saasId) {
        QueryWrapper<UserTagInfo> userTagQry = new QueryWrapper<>();
        userTagQry.eq("uid",uid).eq("saas_id",saasId).eq("is_deleted",0);
        return userTagMapper.selectList(userTagQry);
    }

    /**
     * 批量获取用户基础信息
     *
     * @param request
     * @return
     */
    @Override
    public HttpResult<List<UserBasicInfo>> getUserBasicInfos(UserBasicInfoBatchRequest request) {
        if (!isEmpty(request.getUids()) && request.getUids().size() > 50) {
            return HttpResult.error(ErrorCode.BAD_REQUEST.getCode(), "单次请求uids数组大小不能超过50");
        }
        List<UserBasicInfo> userBasicInfos = userInfoMapper.getUserBasicInfos(request.getUids());
        return HttpResult.success(userBasicInfos);
    }

    @Override
    public HttpResult<IsEditNickNameOrHeadUrlResponse> isEditNickNameOrHeadUrl(String irisUid) {
        boolean isEdit = false;
        IsEditNickNameOrHeadUrlResponse isEditNickNameOrHeadUrlResponse = new IsEditNickNameOrHeadUrlResponse();
        String headUrls = userInfoProperties.getHeadUrls();
        UserCoreInfo userCoreInfo = userCoreInfoMapper.selectByUid(irisUid);
        if (userCoreInfo != null) {
            String nickName = userCoreInfo.getNickName();
            String headUrl = userCoreInfo.getHeadUrl();
            //没有昵称
            if (!StringUtils.isNullOrEmpty(nickName) && !StringUtils.isNullOrEmpty(headUrl)) {
                try {
                    String[] s = nickName.split("_");
                    if (s.length != 2) {
                        isEdit = true;
                    } else {
                        String uid2 = "000000" + irisUid;
                        uid2 = uid2.substring(uid2.length() - 6);
                        //是否为默认昵称， 下划线后半部分为uid后六位，前部分为用户等级
                        Boolean isDefaultNickName = s[1].equals(uid2) && UserLevelEnum.ALL_GROUP_LIST_DESC.contains(s[0]);
                        //头像是否为默认的系统头像
                        Boolean isDefaultHeadUrl = headUrls.contains(headUrl);

                        isEdit = !(isDefaultNickName && isDefaultHeadUrl);
                    }
                } catch (Exception e) {
                    log.error("isEditNickNameOrHeaderUrl parse error, headUrl:{}, nickName:{}, uid:{}， error:{}", headUrl, nickName, irisUid, e.getMessage());
                }
            }
        }
        isEditNickNameOrHeadUrlResponse.setIsEditNickNameOrHeadUrl(isEdit);
        return HttpResult.success(isEditNickNameOrHeadUrlResponse);
    }


    /**
     * 设置用户分层结果
     *
     * @param userPaymentCountDTO
     * @param size
     * @param dtos
     */
    private void setValueByPaymentCount(UserPaymentCountDTO userPaymentCountDTO, int size, List<MksCouponStatusCountDTO> dtos) {
        int couponCount = 0;
        if (!isEmpty(dtos)) {
            couponCount = dtos.get(0).getCount();
        }
        if (size == 0 && couponCount <= 0) {
            // 新用户
            userPaymentCountDTO.setUserType("1");
            return;
        }
        if (size == 1 && couponCount <= 1) {
            userPaymentCountDTO.setUserType("2");
            return;
        }
        if (size == 2 && couponCount <= 2) {
            userPaymentCountDTO.setUserType("3");
            return;
        }
        // 2单以上为活跃用户
        userPaymentCountDTO.setUserType("4");
        return;
    }

    private void setValueByPaymentCountV2(UserPaymentCountDTO userPaymentCountDTO, Long size, Long couponCount) {
        if (size == 0 && couponCount <= 0) {
            // 新用户
            userPaymentCountDTO.setUserType("1");
            return;
        }
        if (size == 1 && couponCount <= 1) {
            userPaymentCountDTO.setUserType("2");
            return;
        }
        if (size == 2 && couponCount <= 2) {
            userPaymentCountDTO.setUserType("3");
            return;
        }
        // 2单以上为活跃用户
        userPaymentCountDTO.setUserType("4");
    }

    private UserPaymentCountCacheDTO queryCache(String unionId) {
        Object value = redisService.getValue(RedisKeyConstants.userPayOrderNos + unionId);
        if (value != null) {
            UserPaymentCountCacheDTO cacheDTO = JSON.parseObject(value.toString(), new TypeReference<UserPaymentCountCacheDTO>() {
            });
            return cacheDTO;
        }
        return null;
    }

    private void cacheOrder(List<OrderDO> list, String unionId) {
        if (isEmpty(list)) {
            return;
        }
        UserPaymentCountCacheDTO cacheDTO = new UserPaymentCountCacheDTO();
        cacheDTO.setOrderCount(list.size());
        Integer successCount = 0;
        List<UserPaymentCountCacheDTO.OrderNo> orderNos = new ArrayList<>();
        for (OrderDO orderDO : list) {
            if ("SUCCESS".equals(orderDO.getOrderStatus())) {
                // 订单状态为成功的订单数
                successCount++;
            } else {
                orderNos.add(new UserPaymentCountCacheDTO.OrderNo(orderDO.getExternalOrderId()));
            }
        }
        if (successCount < 2) {
            cacheDTO.setOrderNos(orderNos);
        }
        redisService.setValue(RedisKeyConstants.userPayOrderNos + unionId,
                JSON.toJSONString(cacheDTO), 8 * 60L, TimeUnit.MINUTES);
    }

    @Override
    public List<UserDO> queryAllUser() {
        UserExample example = new UserExample();
        example.setOrderByClause(" age "); // 设置排序字段
        return userDao.selectByExample(example);
    }
}
